package in.muton.wicket.model;

import in.muton.edushare.EduShareSession;

import org.apache.cayenne.DataObject;
import org.apache.cayenne.DataObjectUtils;
import org.apache.cayenne.ObjectId;
import org.apache.cayenne.PersistenceState;
import org.apache.cayenne.access.DataContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.wicket.model.IModel;

import com.edushare.common.exceptions.EduShareRuntimeException;
import com.edushare.common.orm.CayenneORMInterface;

public class CayenneLoadableDetachableModel implements IModel{

	private static final long serialVersionUID = -4201944718643651027L;
	private static Log log = LogFactory.getLog(CayenneLoadableDetachableModel.class);

	private DataObject entity;
	private ObjectId id;
	
	public CayenneLoadableDetachableModel(DataObject entity){
		
		if(entity.getPersistenceState() == PersistenceState.TRANSIENT){
			this.id = null;
		}else{
			this.id = entity.getObjectId();
		}
		this.entity = entity;
		
		log.debug("Model: Instanciating. Entity: " + this.entity +"; Id: "+ this.id);
	}
	
	public Object getObject() {
		//Normal cases
		if(this.entity == null){
			if(this.id != null){
				this.entity = load(this.id);
				if(this.entity == null){
					throw new EduShareRuntimeException("Entity not found. Id: " + this.id);
				}
			}
		}
		
		//Cayenne entity was serialized and goes to hollow state but ID is still there
		if(this.entity!=null && this.entity.getPersistenceState() == PersistenceState.HOLLOW && this.id != null)
		{
			this.entity = load(this.id);
		}
		
		log.debug("Model: getObject. Entity: " + this.entity +"; Id: "+ this.id);
		return this.entity;
	}

	private DataObject load(ObjectId objId) {
		DataContext ctx = ((CayenneORMInterface)EduShareSession.get().getSessionORMInterface()).getDataContext();
		DataObject dobj = (DataObject)DataObjectUtils.objectForPK(ctx, objId);
		log.debug("Model: loadObject. Entity: " + this.entity +"; Id: "+ this.id +"; Returns: "+ dobj);
		return dobj;
	}

	public void detach() {
		log.debug("Model: detach Object. Entity: " + this.entity +"; Id: "+ this.id);
		if(this.entity != null){
			if(entity.getPersistenceState() != PersistenceState.TRANSIENT){
				log.debug("Model: detach non-TRANSIENT Object.");
				this.id = entity.getObjectId();
				this.entity = null;
			}
		}
		
	}

	public void setObject(Object arg0) {
		log.debug("Model: set Object.");
	}

}
